home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 726-750 / 734 / powervisor / s / pv / assem.pv next >
Text File  |  1995-03-18  |  32KB  |  1,436 lines

  1. /*=======================================================*/
  2. /*                                                                            */
  3. /* Simple assembler for PowerVisor        V1.2                    */
  4. /*                                                                            */
  5. /* © Jorrit Tyberghein  18 Sep 1991    V1.0                        */
  6. /*                                31 Oct 1991 V1.1                        */
  7. /*                                16 Jul 1992 V1.2                        */
  8. /*                                                                            */
  9. /*=======================================================*/
  10.  
  11. /* Usage : execute this script after setting the start address in the 'rc'
  12.               variable (use 'rx' to call this script)
  13.               Press enter to stop the assembler
  14.  
  15.     This assembler assembles the following commands :
  16.  
  17.         move (with movea)
  18.         moveq
  19.         movem
  20.         tst
  21.         add
  22.         sub
  23.         or
  24.         eor
  25.         and
  26.         addi
  27.         subi
  28.         eori
  29.         ori
  30.         andi
  31.         addq
  32.         subq
  33.         not
  34.         nop
  35.         neg
  36.         swap
  37.         illegal
  38.         reset
  39.         rts
  40.         bra
  41.         bsr
  42.         jmp
  43.         jsr
  44.         b<condition>
  45.         negx
  46.         clr
  47.         cmp
  48.         cmpi
  49.         cmpa
  50.         cmpm
  51.         db<condition>
  52.         dbra
  53.         lea
  54.         pea
  55.         dc (only .W and .L)
  56.  
  57.  
  58.     Almost all 68030 addressing modes are supported. Note that you can
  59.     use PowerVisor expressions almost everywhere where a number is
  60.     expected. But don't make these expressions to complex or the parser
  61.     in this assembler will get confused.
  62.                 xxx    number
  63.                 d16    16 bit displacement
  64.                 d8        8 bit displacement
  65.                 bd        base displacement
  66.                 od        outer displacement
  67.                 An        address register
  68.                 Dn        data register
  69.                 Xn        data or address register
  70.                 PC        program counter
  71.  
  72.                 Note that you can append a size specifier (.W or .L) to Xn
  73.                 and a scale factor (*1 2 4 8)
  74.  
  75.         #<data>
  76.         (xxx).W
  77.         (xxx).L
  78.         (d16,PC)
  79.         (d8,PC,Xn)
  80.         (bd,PC,Xn)
  81.         ([bd,PC,Xn],od)
  82.         ([bd,PC],Xn,od)
  83.         (d16,An)
  84.         (d8,An,Xn)
  85.         (bd,An,Xn)
  86.         ([bd,An,Xn],od)
  87.         ([bd,An],Xn,od)
  88.         (An)+
  89.         -(An)
  90.         (An)
  91.         An
  92.         Dn
  93.  
  94.  
  95.     Instead of a machinelanguage command you can also use dot commands. Start
  96.     the following commands with a dot :
  97.  
  98.         b            goto previous instruction
  99.         pc            set new program counter
  100.         q            quit assembler (same as empty line)
  101.         h            for dot command help
  102.         to            toggle old mode
  103.         tc            toggle commandline mode
  104.         c            copy current instruction to cmdline
  105.         s            skip the current instruction (only in old or cmd mode)
  106.         cc            copy current instruction to buffer
  107.         gc            copy buffer to cmdline
  108.  
  109.  
  110.     Warning ! This assembler also assembles instructions even if there is
  111.     no meaningfull interpretation. For example, you can assemble :
  112.  
  113.         move.l #1,#2
  114.  
  115.  
  116.     Warning ! When the assembler is stopped because of an internal error
  117.     (this can occur when your expressions are too complex), it looks as
  118.     if PowerVisor hangs. Type the following command on the CLI to get
  119.     PowerVisor back in control :
  120.  
  121.         rx "address rexx_powervisor async"
  122.  
  123. */
  124.  
  125.  
  126. options results
  127.  
  128. /* The following assignments are the default modes. You can change the defaults */
  129. /* if you want */
  130. oldmode=1    /* Old mode, when true we display old instruction on screen */
  131. cmdmode=0    /* Cmd mode, when true we copy old instruction to string gadget */
  132.  
  133. 'unhide'
  134. 'sync'        /* Disable the PowerVisor commandline. We take control */
  135. 'void rc'    /* 'rc' contains address to start assembling, copy to ARexx variable */
  136. pc=result    /* 'pc' always contains the current program counter */
  137. oldpc=0        /* The previous program counter (used by the .B command) */
  138.  
  139. tmpcmd=0        /* Used by the .C command to temporary set cmdmode to true */
  140. buffer=''    /* Empty buffer */
  141.  
  142. 'void getcol(getlwin())'
  143. col=result    /* Number of columns on PowerVisor default logical window */
  144.  
  145.  
  146. /*-----------*/
  147. /* Main loop */
  148. /*-----------*/
  149.  
  150. do forever
  151.     'print "\('pc',%08lx) : "'        /* Print current address (program counter) */
  152.     'getx'                                /* Get coordinates on screen after address */
  153.     x=result
  154.     'gety'
  155.     y=result
  156.  
  157.     /*** If oldmode or cmdmode =1 we need the disassembly of the old instruction ***/
  158.     if (oldmode=1) | (cmdmode=1) | (tmpcmd>=1) then
  159.         do
  160.             'assign _mem=alloc(n,120)'
  161.             'pvcall 64 _mem' pc '0'    /* Disassemble */
  162.             isize=result                /* Result is size of old instruction */
  163.             'string _mem'                /* Copy string to ARexx */
  164.             oldasmstr=result
  165.             'free _mem'
  166.         end
  167.  
  168.     if oldmode=1 then                    /* We must show the old instruction */
  169.         do
  170.             'locate' x y
  171.             'print "'oldasmstr
  172.         end
  173.  
  174.     if tmpcmd=2 then 'void {pv 10 "'buffer'";scan *"INST"}'
  175.     else if (cmdmode=1) | (tmpcmd=1) then 'void {pv 10 "'oldasmstr'";scan *"INST"}'
  176.     else 'void {scan *"INST"}'
  177.     tmpcmd=0
  178.  
  179.     'string input'                        /* Get new instruction string (or dot command) */
  180.     asmstr=result
  181.  
  182.     'locate' x y                        /* Clear line after program counter */
  183.     'print "'copies(' ',col-x-1)'"'
  184.     'locate' x y                        /* Print instruction or dot command */
  185.     'print "'asmstr
  186.  
  187.     /*** First check if it is a dot command ***/
  188.     if substr(asmstr,1,1)='.' then
  189.         do
  190.             parse upper var asmstr '.' dotcmd args
  191.             if dotcmd='Q' then
  192.                 do
  193.                     'print \0a'
  194.                     'async'
  195.                     exit
  196.                 end
  197.             else if dotcmd='PC' then
  198.                 do
  199.                     'void' args
  200.                     if rc~=0 then 'print "\0aBad expression for programcounter !"'
  201.                     else
  202.                         do
  203.                             if (result=0) | (result%1=1) then
  204.                                 'print "\0aBad expression for programcounter !"'
  205.                             else pc=result
  206.                         end
  207.                 end
  208.             else if dotcmd='B' then
  209.                 do
  210.                     if oldpc=0 then
  211.                         'print "\0aNo previous program counter !"'
  212.                     else
  213.                         do
  214.                             pc=oldpc
  215.                             oldpc=0
  216.                         end
  217.                 end
  218.             else if dotcmd='GC' then tmpcmd=2
  219.             else if dotcmd='CC' then
  220.                 do
  221.                     'assign _mem=alloc(n,120)'
  222.                     'pvcall 64 _mem' pc '0'    /* Disassemble */
  223.                     isize=result                /* Result is size of old instruction */
  224.                     'string _mem'                /* Copy string to ARexx */
  225.                     buffer=result
  226.                     'free _mem'
  227.                 end
  228.             else if dotcmd='TO' then oldmode=1-oldmode
  229.             else if dotcmd='TC' then cmdmode=1-cmdmode
  230.             else if dotcmd='C' then tmpcmd=1
  231.             else if dotcmd='S' then
  232.                 do
  233.                     if (oldmode=1) | (cmdmode=1) then
  234.                         do
  235.                             pc=pc+isize
  236.                             'locate' x y
  237.                             'print "'oldasmstr
  238.                         end
  239.                     else 'print "\0aOnly use .s in <old mode> or <cmd mode> !"'
  240.                 end
  241.             else if dotcmd='H' then
  242.                 do
  243.                     'print "\0aMini Assembler V1.1\0a\0a"'
  244.                     'print ".b    goto previous instruction (only once)\0a"'
  245.                     'print ".pc   set new program counter\0a"'
  246.                     'print ".to   toggle <old mode> (ON/off)\0a"'
  247.                     'print ".tc   toggle <cmdline mode> (on/OFF)\0a"'
  248.                     'print ".c    copy current instruction to commandline\0a"'
  249.                     'print ".s    skip this instruction (in old or cmd mode)\0a"'
  250.                     'print ".cc   copy current instruction to buffer\0a"'
  251.                     'print ".gc   copy buffer to commandline\0a"'
  252.                     'print ".q    quit assembler (same as empty line)\0a"'
  253.                     'print ".h    this help\0a"'
  254.                 end
  255.             else 'print "\0aUnknown dot command (type .H for help) !"'
  256.             'print \0a'
  257.         end
  258.     /*** Else it could be an empty string (equivalent to .Q) ***/
  259.     else if asmstr='' then
  260.         do
  261.             'print \0a'
  262.             'async'
  263.             exit
  264.         end
  265.     /*** Else it should be a valid instruction ***/
  266.     else
  267.         do
  268.             'print \0a'
  269.             oldpc=pc
  270.             a=Assemble(asmstr)
  271.         end
  272. end
  273.  
  274.  
  275.  
  276. /*-----------------------------*/
  277. /* Assemble a string to memory */
  278. /*                                         */
  279. /* Input   : string                 */
  280. /* Uses    : pc                     */
  281. /* Changes : pc                     */
  282. /* Returns : 0 if error or 1     */
  283. /*-----------------------------*/
  284.  
  285. Assemble: procedure expose pc
  286. parse upper arg asmstr
  287.  
  288. parse var asmstr cmd arg
  289. cmd=strip(cmd)
  290. arg=strip(arg)
  291.  
  292. parse var cmd opcode '.' size
  293.  
  294. extra=0
  295.  
  296. if opcode='MOVE' then
  297.     do
  298.         call SplitArgs arg
  299.  
  300.         if source='CCR' then
  301.             do
  302.                 mdest=ModeBits(dest)
  303.                 if mdest=-1 then return 0
  304.                 code=x2d('42c0')
  305.                 arb=ArgRegBits(mdest'|'dest)
  306.                 if arb=-1 then return 0
  307.                 code=code+mdest*8+arb
  308.                 call PushWord code
  309.                 extwrd=extra
  310.                 if GetArg(mdest'|'dest'|W')=-1 then return 0
  311.             end
  312.         else if dest='CCR' then
  313.             do
  314.                 msource=ModeBits(source)
  315.                 if msource=-1 then return 0
  316.                 code=x2d('44c0')
  317.                 arb=ArgRegBits(msource'|'source)
  318.                 if arb=-1 then return 0
  319.                 code=code+msource*8+arb
  320.                 call PushWord code
  321.                 extwrd=extra
  322.                 if GetArg(msource'|'source'|W')=-1 then return 0
  323.             end
  324.         else if source='SR' then
  325.             do
  326.                 mdest=ModeBits(dest)
  327.                 if mdest=-1 then return 0
  328.                 code=x2d('40c0')
  329.                 arb=ArgRegBits(mdest'|'dest)
  330.                 if arb=-1 then return 0
  331.                 code=code+mdest*8+arb
  332.                 call PushWord code
  333.                 extwrd=extra
  334.                 if GetArg(mdest'|'dest'|W')=-1 then return 0
  335.             end
  336.         else if dest='SR' then
  337.             do
  338.                 msource=ModeBits(source)
  339.                 if msource=-1 then return 0
  340.                 code=x2d('46c0')
  341.                 arb=ArgRegBits(msource'|'source)
  342.                 if arb=-1 then return 0
  343.                 code=code+msource*8+arb
  344.                 call PushWord code
  345.                 extwrd=extra
  346.                 if GetArg(msource'|'source'|W')=-1 then return 0
  347.             end
  348.         else if source='USP' then
  349.             do
  350.                 if substr(dest,1,1)~='A' then
  351.                     do
  352.                         'print "Only address register allowed !\0a"'
  353.                         return 0
  354.                     end
  355.                 rb=RegBits(dest)
  356.                 if rb=-1 then return 0
  357.                 code=x2d('4e68')+rb
  358.                 call PushWord code
  359.             end
  360.         else if dest='USP' then
  361.             do
  362.                 if substr(source,1,1)~='A' then
  363.                     do
  364.                         'print "Only address register allowed !\0a"'
  365.                         return 0
  366.                     end
  367.                 rb=RegBits(source)
  368.                 if rb=-1 then return 0
  369.                 code=x2d('4e60')+rb
  370.                 call PushWord code
  371.             end
  372.         else
  373.             do
  374.                 mdest=ModeBits(dest)
  375.                 if mdest=-1 then return 0
  376.                 msource=ModeBits(source)
  377.                 if msource=-1 then return 0
  378.                 msb=MoveSizeBits(size)
  379.                 if msb=-1 then return 0
  380.                 code=msb*4096+mdest*64+msource*8
  381.                 arb=ArgRegBits(mdest'|'dest)
  382.                 if arb=-1 then return 0
  383.                 code=code+arb*512
  384.                 arb=ArgRegBits(msource'|'source)
  385.                 if arb=-1 then return 0
  386.                 code=code+arb
  387.                 call PushWord code
  388.                 extwrd=extra
  389.                 if GetArg(msource'|'source'|'size)=-1 then return 0
  390.                 extwrd=extwrd+extwrd-extra
  391.                 if GetArg(mdest'|'dest'|'size)=-1 then return 0
  392.             end
  393.     end
  394. else if (substr(opcode,1,1)='B') & (length(opcode)=3) then
  395.     do
  396.         'void' arg
  397.         if rc~=0 then
  398.             do
  399.                 'print "Bad integer !\0a"'
  400.                 return 0
  401.             end
  402.         arg=result
  403.         arg=arg-pc-2
  404.  
  405.         if opcode='BRA' then code=x2d('6000')
  406.         else if opcode='BSR' then code=x2d('6100')
  407.         else
  408.             do
  409.                 p=pos(substr(opcode,2,2),'HI LS CC CS NE EQ VC VS PL MI GE LT GT LE')
  410.                 if p=0 then
  411.                     do
  412.                         'print "Unknown opcode !\0a"'
  413.                         return 0
  414.                     end
  415.                 else code=x2d('6000')+((p-1)/3+2)*256
  416.             end
  417.  
  418.         if (size='B') | (size='S') then call PushWord code+MakeByte(arg)
  419.         else if (size='W') | (size='') then
  420.             do
  421.                 call PushWord code
  422.                 call PushWord arg
  423.             end
  424.         else if size='L' then
  425.             do
  426.                 call PushWord code+255
  427.                 call PushLong arg
  428.             end
  429.     end
  430. else if opcode='RTS' then call PushWord x2d('4e75')
  431. else if opcode='NOP' then call PushWord x2d('4e71')
  432. else if (opcode='TST') | (opcode='CLR') | (opcode='NEG') | (opcode='NEGX') | (opcode='NOT') then
  433.     do
  434.         msource=ModeBits(arg)
  435.         if msource=-1 then return 0
  436.         sb=SizeBits(size)
  437.         if sb=-1 then return 0
  438.         sb=sb*64
  439.         if opcode='TST' then code=x2d('4a00')+sb
  440.         else if opcode='NEG' then code=x2d('4400')+sb
  441.         else if opcode='NEGX' then code=x2d('4000')+sb
  442.         else if opcode='NOT' then code=x2d('4600')+sb
  443.         else code=x2d('4200')+sb
  444.         arb=ArgRegBits(msource'|'arg)
  445.         if arb=-1 then return 0
  446.         code=code+msource*8+arb
  447.         call PushWord code
  448.         extwrd=extra
  449.         if GetArg(msource'|'arg'|'size)=-1 then return 0
  450.     end
  451. else if (opcode='ADD') | (opcode='SUB') | (opcode='AND') | (opcode='OR') then
  452.     do
  453.         call SplitArgs arg
  454.         if opcode='ADD' then firstnib=x2d('d000')
  455.         else if opcode='SUB' then firstnib=x2d('9000')
  456.         else if opcode='OR' then firstnib=x2d('8000')
  457.         else firstnib=x2d('c000')
  458.  
  459.         if substr(dest,1,1)='D' then
  460.             do
  461.                 sb=SizeBits(size)
  462.                 if sb=-1 then return 0
  463.                 rb=RegBits(dest)
  464.                 if rb=-1 then return 0
  465.                 code=firstnib+rb*512+sb*64
  466.                 dest=source
  467.             end
  468.         else if substr(source,1,1)='D' then
  469.             do
  470.                 sb=SizeBits(size)
  471.                 if sb=-1 then return 0
  472.                 rb=RegBits(source)
  473.                 if rb=-1 then return 0
  474.                 code=firstnib+x2d('0100')+rb*512+sb*64
  475.             end
  476.         else
  477.             do
  478.                 'print "Must have at least one data register !\0a"'
  479.                 return 0
  480.             end
  481.         mdest=ModeBits(dest)
  482.         if mdest=-1 then return 0
  483.         arb=ArgRegBits(mdest'|'dest)
  484.         if arb=-1 then return 0
  485.         code=code+mdest*8+arb
  486.         call PushWord code
  487.         extwrd=extra
  488.         if GetArg(mdest'|'dest'|'size)=-1 then return 0
  489.     end
  490. else if (opcode='ADDA') | (opcode='SUBA') then
  491.     do
  492.         call SplitArgs arg
  493.         if substr(dest,1,1)='A' then
  494.             do
  495.                 s=AddressSizeBits(size)
  496.                 if s=-1 then return 0
  497.                 if opcode='ADD' then firstnib=x2d('d000')
  498.                 else firstnib=x2d('9000')
  499.                 rb=RegBits(dest)
  500.                 if rb=-1 then return 0
  501.                 code=firstnib+rb*512+s*64
  502.                 msource=ModeBits(source)
  503.                 if msource=-1 then return 0
  504.                 arb=ArgRegBits(msource'|'source)
  505.                 if arb=-1 then return 0
  506.                 code=code+msource*8+arb
  507.                 call PushWord code
  508.                 extwrd=extra
  509.                 if GetArg(msource'|'source'|'size)=-1 then return 0
  510.             end
  511.         else
  512.             do
  513.                 'print "ADDA must have a destination address register !\0a"'
  514.                 return 0
  515.             end
  516.     end
  517. else if (opcode='ADDI') | (opcode='SUBI') | (opcode='ADDQ') | (opcode='SUBQ') | (opcode='ANDI') | (opcode='CMPI') | (opcode='EORI') | (opcode='ORI') then
  518.     do
  519.         call SplitArgs arg
  520.         if substr(source,1,1)~='#' then
  521.             do
  522.                 'print "Bad immediate value !\0a"'
  523.                 return 0
  524.             end
  525.  
  526.         parse var source '#' imm
  527.         'void' imm
  528.         if rc~=0 then
  529.             do
  530.                 'print "Bad integer !\0a"'
  531.                 return 0
  532.             end
  533.         imm=result
  534.  
  535.         mdest=ModeBits(dest)
  536.         if mdest=-1 then return 0
  537.         sb=SizeBits(size)
  538.         if sb=-1 then return 0
  539.         arb=ArgRegBits(mdest'|'dest)
  540.         if arb=-1 then return 0
  541.         sb=sb*64+mdest*8+arb
  542.         if opcode='ADDI' then code=x2d('0600')+sb
  543.         else if opcode='SUBI' then code=x2d('0400')+sb
  544.         else if opcode='ANDI' then code=x2d('0200')+sb
  545.         else if opcode='ORI' then code=x2d('0000')+sb
  546.         else if opcode='CMPI' then code=x2d('0c00')+sb
  547.         else if opcode='EORI' then code=x2d('0a00')+sb
  548.         else if opcode='SUBQ' then code=x2d('5100')+sb+imm*512
  549.         else code=x2d('5000')+sb+imm*512
  550.  
  551.         call PushWord code
  552.  
  553.         if substr(opcode,4,1)~='Q' then
  554.             do
  555.                 if size='B' then call PushWord imm
  556.                 else if (size='W') | (size='') then call PushWord imm
  557.                 else call PushLong imm
  558.             end
  559.  
  560.         extwrd=extra
  561.         if GetArg(mdest'|'dest'|'size)=-1 then return 0
  562.     end
  563. else if opcode='CMP' then
  564.     do
  565.         call SplitArgs arg
  566.  
  567.         if substr(dest,1,1)='D' then
  568.             do
  569.                 sb=SizeBits(size)
  570.                 if sb=-1 then return 0
  571.                 rb=RegBits(dest)
  572.                 if rb=-1 then return 0
  573.                 code=x2d('b000')+rb*512+sb*64
  574.             end
  575.         else
  576.             do
  577.                 'print "Destination must be a data register !\0a"'
  578.                 return 0
  579.             end
  580.         msource=ModeBits(source)
  581.         if msource=-1 then return 0
  582.         arb=ArgRegBits(msource'|'source)
  583.         if arb=-1 then return 0
  584.         code=code+msource*8+arb
  585.         call PushWord code
  586.         extwrd=extra
  587.         if GetArg(msource'|'source'|'size)=-1 then return 0
  588.     end
  589. else if opcode='CMPA' then
  590.     do
  591.         call SplitArgs arg
  592.  
  593.         if substr(dest,1,1)='A' then
  594.             do
  595.                 asb=AddressSizeBits(size)
  596.                 if asb=-1 then return 0
  597.                 rb=RegBits(dest)
  598.                 if rb=-1 then return 0
  599.                 code=x2d('b000')+rb*512+asb*64
  600.             end
  601.         else
  602.             do
  603.                 'print "Destination must be an address register !\0a"'
  604.                 return 0
  605.             end
  606.         msource=ModeBits(source)
  607.         if msource=-1 then return 0
  608.         arb=ArgRegBits(msource'|'source)
  609.         if arb=-1 then return 0
  610.         code=code+msource*8+arb
  611.         call PushWord code
  612.         extwrd=extra
  613.         if GetArg(msource'|'source'|'size)=-1 then return 0
  614.     end
  615. else if opcode='CMPM' then
  616.     do
  617.         call SplitArgs arg
  618.  
  619.         parse var source '(A' sreg ')+'
  620.         parse var dest '(A' dreg ')+'
  621.         sreg='A'sreg
  622.         dreg='A'dreg
  623.  
  624.         sb=SizeBits(size)
  625.         if sb=-1 then return 0
  626.         rb=RegBits(sreg)
  627.         if rb=-1 then return 0
  628.         rbd=RegBits(dreg)
  629.         if rbd=-1 then return 0
  630.         code=x2d('b108')+sb*64+rb*512+rbd
  631.         call PushWord code
  632.     end
  633. else if ((substr(opcode,1,2)='DB') & (length(opcode)=4)) | (opcode='DBT') | (opcode='DBF') then
  634.     do
  635.         if opcode='DBT' then code=x2d('50c8')
  636.         else if (opcode='DBF') | (opcode='DBRA') then code=x2d('51c8')
  637.         else
  638.             do
  639.                 p=pos(substr(opcode,3,2),'HI LS CC CS NE EQ VC VS PL MI GE LT GT LE')
  640.                 if p=0 then
  641.                     do
  642.                         'print "Unknown opcode !\0a"'
  643.                         return 0
  644.                     end
  645.                 else code=x2d('50c8')+((p-1)/3+2)*256
  646.             end
  647.  
  648.         call SplitArgs arg
  649.         if substr(source,1,1)~='D' then
  650.             do
  651.                 'print "Count register must be a data register !\0a"'
  652.                 return 0
  653.             end
  654.         rb=RegBits(source)
  655.         if rb=-1 then return 0
  656.         code=code+rb
  657.         call PushWord code
  658.         'void' dest
  659.         if rc~=0 then
  660.             do
  661.                 'print "Bad integer !\0a"'
  662.                 return 0
  663.             end
  664.         dest=result
  665.         dest=dest-pc-2
  666.         call PushWord dest
  667.     end
  668. else if opcode='EOR' then
  669.     do
  670.         call SplitArgs arg
  671.  
  672.         if substr(source,1,1)='D' then
  673.             do
  674.                 sb=SizeBits(size)
  675.                 if sb=-1 then return 0
  676.                 rb=RegBits(source)
  677.                 if rb=-1 then return 0
  678.                 code=x2d('b100')+rb*512+sb*64
  679.             end
  680.         else
  681.             do
  682.                 'print "Source must be a data register !\0a"'
  683.                 return 0
  684.             end
  685.         mdest=ModeBits(dest)
  686.         if mdest=-1 then return 0
  687.         arb=ArgRegBits(mdest'|'dest)
  688.         if arb=-1 then return 0
  689.         code=code+mdest*8+arb
  690.         call PushWord code
  691.         extwrd=extra
  692.         if GetArg(mdest'|'dest'|'size)=-1 then return 0
  693.     end
  694. else if opcode='ILLEGAL' then call PushWord x2d('4afc')
  695. else if opcode='RESET' then call PushWord x2d('4e70')
  696. else if (opcode='JMP') | (opcode='JSR') then
  697.     do
  698.         if opcode='JMP' then code=x2d('4ec0')
  699.         else code=x2d('4e80')
  700.         marg=ModeBits(arg)
  701.         if marg=-1 then return 0
  702.         arb=ArgRegBits(marg'|'arg)
  703.         if arb=-1 then return 0
  704.         code=code+marg*8+arb
  705.         call PushWord code
  706.         extwrd=extra
  707.         if GetArg(marg'|'arg'|W')=-1 then return 0
  708.     end
  709. else if opcode='LEA' then
  710.     do
  711.         call SplitArgs arg
  712.  
  713.         if substr(dest,1,1)='A' then
  714.             do
  715.                 rb=RegBits(dest)
  716.                 if rb=-1 then return 0
  717.                 code=x2d('41c0')+rb*512
  718.             end
  719.         else
  720.             do
  721.                 'print "Destination must be an address register !\0a"'
  722.                 return 0
  723.             end
  724.         msource=ModeBits(source)
  725.         if msource=-1 then return 0
  726.         arb=ArgRegBits(msource'|'source)
  727.         if arb=-1 then return 0
  728.         code=code+msource*8+arb
  729.         call PushWord code
  730.         extwrd=extra
  731.         if GetArg(msource'|'source'|L')=-1 then return 0
  732.     end
  733. else if opcode='MOVEM' then
  734.     do
  735.         call SplitArgs arg
  736.  
  737.         if (pos('-',source)~=0) | (pos('/',source)~=0) | ((length(source)=2) & (pos(substr(source,1,1),'DA')~=0)) then
  738.             do
  739.                 list=source
  740.                 arg=dest
  741.                 code=x2d('4880')
  742.             end
  743.         else
  744.             do
  745.                 list=dest
  746.                 arg=source
  747.                 code=x2d('4c80')
  748.             end
  749.  
  750.         bits=RegListBits(list)
  751.         if bits=-1 then return 0
  752.         if substr(arg,1,2)~='-(' then bits=reverse(bits)
  753.         rlbits=c2d(b2c(bits))
  754.  
  755.         asb=AddressSizeBits(size)
  756.         if asb=-1 then return 0
  757.         code=code+(asb%4)*64
  758.  
  759.         marg=ModeBits(arg)
  760.         if marg=-1 then return 0
  761.         arb=ArgRegBits(marg'|'arg)
  762.         if arb=-1 then return 0
  763.         code=code+marg*8+arb
  764.         call PushWord code
  765.         call PushWord rlbits
  766.         extwrd=extra
  767.         if GetArg(marg'|'arg'|'size)=-1 then return 0
  768.     end
  769. else if opcode='MOVEQ' then
  770.     do
  771.         call SplitArgs arg
  772.         if substr(source,1,1)~='#' then
  773.             do
  774.                 'print "Bad immediate value !\0a"'
  775.                 return 0
  776.             end
  777.         if substr(dest,1,1)~='D' then
  778.             do
  779.                 'print "Destination must be a data register !\0a"'
  780.                 return 0
  781.             end
  782.  
  783.         parse var source '#' imm
  784.         'void' imm
  785.         if rc~=0 then
  786.             do
  787.                 'print "Bad integer !\0a"'
  788.                 return 0
  789.             end
  790.         imm=result
  791.  
  792.         rb=RegBits(dest)
  793.         if rb=-1 then return 0
  794.         code=x2d('7000')+rb*512+MakeByte(imm)
  795.         call PushWord code
  796.     end
  797. else if opcode='PEA' then
  798.     do
  799.         msource=ModeBits(arg)
  800.         if msource=-1 then return 0
  801.         code=x2d('4840')
  802.         arb=ArgRegBits(msource'|'arg)
  803.         if arb=-1 then return 0
  804.         code=code+msource*8+arb
  805.         call PushWord code
  806.         extwrd=extra
  807.         if GetArg(msource'|'arg'|L')=-1 then return 0
  808.     end
  809. else if opcode='SWAP' then
  810.     do
  811.         if substr(arg,1,1)~='D' then
  812.             do
  813.                 'print "Argument must be a data register !\0a"'
  814.                 return 0
  815.             end
  816.         rb=RegBits(arg)
  817.         if rb=-1 then return 0
  818.         code=x2d('4840')+rb
  819.         call PushWord code
  820.     end
  821. else if opcode='DC' then
  822.     do
  823.         'void' arg
  824.         if rc~=0 then
  825.             do
  826.                 'print "Bad integer !\0a"'
  827.                 return 0
  828.             end
  829.         arg=result
  830.         if size='B' then
  831.             do
  832.                 'print "Sorry DC.B not supported !\0a"'
  833.                 return 0
  834.             end
  835.         if (size='W') | (size='') then call PushWord arg
  836.         else if size='L' then call PushLong arg
  837.         else
  838.             do
  839.                 'print "Bad size specifier !\0a"'
  840.                 return 0
  841.             end
  842.     end
  843. else
  844.     do
  845.         'print "Unknown opcode !\0a"'
  846.         return 0
  847.     end
  848.  
  849. 'assign _m='pc
  850. do j=0 to extra-1
  851.     'assign *(_m+'j'*2).w='c.j
  852. end
  853. pc=pc+extra*2
  854. return 1
  855.  
  856.  
  857. /*-------------------------------*/
  858. /* Convert size specifier for     */
  859. /* MOVE to bits                        */
  860. /*                                            */
  861. /* Input   : size .B, .W, .L        */
  862. /* Uses    :                             */
  863. /* Changes :                             */
  864. /* Returns : -1 if error or bits    */
  865. /*-------------------------------*/
  866.  
  867. MoveSizeBits: procedure
  868. parse arg size
  869.  
  870.     if size='B' then return 1
  871.     else if (size='W') | (size='') then return 3
  872.     else if size='L' then return 2
  873.     else
  874.         do
  875.             'print "Bad size specifier !\0a"'
  876.             return -1
  877.         end
  878.  
  879.  
  880. /*-------------------------------*/
  881. /* Convert size specifier for     */
  882. /* address registers to bits        */
  883. /*                                            */
  884. /* Input   : size .W, .L            */
  885. /* Uses    :                             */
  886. /* Changes :                             */
  887. /* Returns : -1 if error or bits    */
  888. /*-------------------------------*/
  889.  
  890. AddressSizeBits: procedure
  891. parse arg size
  892.  
  893.     if (size='W') | (size='') then return 3
  894.     else if size='L' then return 7
  895.     else
  896.         do
  897.             'print "Bad size specifier !\0a"'
  898.             return -1
  899.         end
  900.  
  901.  
  902. /*-------------------------------*/
  903. /* Convert size specifier            */
  904. /* to bits                                */
  905. /*                                            */
  906. /* Input   : size .B, .W, .L        */
  907. /* Uses    :                             */
  908. /* Changes :                             */
  909. /* Returns : -1 if error or bits    */
  910. /*-------------------------------*/
  911.  
  912. SizeBits: procedure
  913. parse arg size
  914.  
  915.     if size='B' then return 0
  916.     else if (size='W') | (size='') then return 1
  917.     else if size='L' then return 2
  918.     else
  919.         do
  920.             'print "Bad size specifier !\0a"'
  921.             return -1
  922.         end
  923.  
  924.  
  925. /*-------------------------------*/
  926. /* Convert register to bits        */
  927. /*                                            */
  928. /* Input   : reg A0..A7 D0..D7    */
  929. /* Uses    :                             */
  930. /* Changes :                             */
  931. /* Returns : -1 if error or bits    */
  932. /*-------------------------------*/
  933.  
  934. RegBits: procedure
  935. parse arg reg
  936.  
  937.     l=substr(reg,1,1)
  938.     if ((l='D') | (l='A')) & (length(reg)=2) then return substr(reg,2,1)
  939.     else
  940.         do
  941.             'print "Bad register name !\0a"'
  942.             return -1
  943.         end
  944.  
  945.  
  946. /*-------------------------------*/
  947. /* Convert parameter to bits        */
  948. /* corresponding with mode field    */
  949. /* in most instructions                */
  950. /*                                            */
  951. /* Input   : addressing arg        */
  952. /* Uses    :                             */
  953. /* Changes :                             */
  954. /* Returns : -1 if error or bits    */
  955. /*-------------------------------*/
  956.  
  957. ModeBits: procedure
  958. parse arg argum
  959.  
  960.     l=substr(argum,1,1)
  961.     if l='(' then
  962.         do
  963.             if pos('PC',argum) ~= 0 then return 7
  964.             l=substr(argum,2,1)
  965.             if l='A' then
  966.                 do
  967.                     if substr(argum,5,1)='+' then return 3
  968.                     else return 2
  969.                 end
  970.             else
  971.                 do
  972.                     if pos(',',argum)=0 then return 7
  973.                     parse var argum left ',' right
  974.                     if pos(',',right)=0 then return 5
  975.                     else return 6
  976.                 end
  977.         end
  978.     else if l='A' then return 1
  979.     else if l='D' then return 0
  980.     else if l='-' then return 4
  981.     else if l='#' then return 7
  982.     else
  983.         do
  984.             'print "Bad argument format !\0a"'
  985.             return -1
  986.         end
  987.  
  988.  
  989. /*-------------------------------------*/
  990. /* Convert parameter to bits                */
  991. /* corresponding with register            */
  992. /* field in most instructions                */
  993. /* ('mode' in Input is the value            */
  994. /* returned by 'ModeBits')                    */
  995. /*                                                    */
  996. /* Input   : mode '|' addressing arg    */
  997. /* Uses    :                                     */
  998. /* Changes :                                     */
  999. /* Returns : -1 if error or bits            */
  1000. /*-------------------------------------*/
  1001.  
  1002. ArgRegBits: procedure
  1003. parse arg mode '|' argum
  1004.  
  1005.     if (mode=0) | (mode=1) then return RegBits(argum)
  1006.     else if (mode=2) | (mode=3) | (mode=4) then
  1007.         do
  1008.             parse var argum '(A' reg
  1009.             reg=substr(reg,1,1)
  1010.             return RegBits('A'reg)
  1011.         end
  1012.     else if mode~=7 then    /* 5 and 6 */
  1013.         do
  1014.             parse var argum ',A' reg
  1015.             reg=substr(reg,1,1)
  1016.             return RegBits('A'reg)
  1017.         end
  1018.     else
  1019.         do
  1020.             l=substr(argum,1,1)
  1021.             if l='#' then return 4
  1022.             else
  1023.                 do
  1024.                     parse var argum '(' xxx ')' yyy
  1025.                     if yyy='.W' then return 0
  1026.                     else if yyy='.L' then return 1
  1027.  
  1028.                     parse var argum '(' xxx ',' yyy
  1029.                     if yyy='PC)' then return 2
  1030.                     else if index(argum,'PC') ~= 0 then return 3
  1031.                     else return 1
  1032.                 end
  1033.         end
  1034.  
  1035.  
  1036. /*-------------------------*/
  1037. /* Push a word to memory    */
  1038. /*                                    */
  1039. /* Input   : word to push    */
  1040. /* Uses    : c. extra        */
  1041. /* Changes : c. extra        */
  1042. /* Returns :                    */
  1043. /*-------------------------*/
  1044.  
  1045. PushWord: procedure expose c. extra
  1046. parse arg word
  1047.  
  1048.     c.extra=MakeWord(word)
  1049.     extra=extra+1
  1050.     return
  1051.  
  1052.  
  1053. /*-------------------------*/
  1054. /* Push a long to memory    */
  1055. /*                                    */
  1056. /* Input   : long to push    */
  1057. /* Uses    : c. extra        */
  1058. /* Changes : c. extra        */
  1059. /* Returns :                    */
  1060. /*-------------------------*/
  1061.  
  1062. PushLong: procedure expose c. extra
  1063. parse arg long
  1064.  
  1065.     c.extra=MakeWord(x2d(left(d2x(long,8),4)))
  1066.     extra=extra+1
  1067.     c.extra=MakeWord(x2d(d2x(long,4)))
  1068.     extra=extra+1
  1069.     return
  1070.  
  1071.  
  1072. /*----------------------------------------------*/
  1073. /* Parse a normal addressing argument                */
  1074. /* and push words to memory                            */
  1075. /*                                                                */
  1076. /* Input   : mode '|' addressing arg '|' size    */
  1077. /* Uses    : c. extra pc extwrd                        */
  1078. /* Changes : c. extra                                    */
  1079. /* Returns : -1 if error or 0                            */
  1080. /*----------------------------------------------*/
  1081.  
  1082. GetArg: procedure expose c. extra pc extwrd
  1083. parse arg mode '|' argum '|' size
  1084.  
  1085.     if (mode=0) | (mode=1) | (mode=2) | (mode=3) | (mode=4) then
  1086.         return 0
  1087.     else if mode=5 then
  1088.         do
  1089.             parse var argum '(' xxx ','
  1090.             'void' xxx
  1091.             if rc~=0 then
  1092.                 do
  1093.                     'print "Bad integer !\0a"'
  1094.                     return -1
  1095.                 end
  1096.             xxx=result
  1097.             if (xxx<=32767) & (xxx>=-32768) then call PushWord xxx
  1098.             else if (xxx<=65535) & (xxx>=0) then call PushWord xxx
  1099.             else
  1100.                 do
  1101.                     'print "Sorry, longword Ax relative not supported !\0a"'
  1102.                     return -1
  1103.                 end
  1104.             return 0
  1105.         end
  1106.     else if mode=7 then
  1107.         do
  1108.             reg=ArgRegBits(mode'|'argum)
  1109.             if reg=-1 then return -1
  1110.             else if reg=0 then
  1111.                 do
  1112.                     parse var argum '(' xxx ')'
  1113.                     'void' xxx
  1114.                     if rc~=0 then
  1115.                         do
  1116.                             'print "Bad integer !\0a"'
  1117.                             return -1
  1118.                         end
  1119.                     call PushWord result
  1120.                     return 0
  1121.                 end
  1122.             else if reg=1 then
  1123.                 do
  1124.                     parse var argum '(' xxx ')'
  1125.                     'void' xxx
  1126.                     if rc~=0 then
  1127.                         do
  1128.                             'print "Bad integer !\0a"'
  1129.                             return -1
  1130.                         end
  1131.                     call PushLong result
  1132.                     return 0
  1133.                 end
  1134.             else if reg=4 then
  1135.                 do
  1136.                     s=MoveSizeBits(size)
  1137.                     if s=-1 then return -1
  1138.                     parse var argum '#' xxx
  1139.                     'void' xxx
  1140.                     if rc~=0 then
  1141.                         do
  1142.                             'print "Bad integer !\0a"'
  1143.                             return -1
  1144.                         end
  1145.                     xxx=result
  1146.                     if s=2 then call PushLong xxx
  1147.                     else call PushWord xxx
  1148.                     return 0
  1149.                 end
  1150.             else if reg=2 then
  1151.                 do
  1152.                     parse var argum '(' xxx ','
  1153.                     'void' xxx
  1154.                     if rc~=0 then
  1155.                         do
  1156.                             'print "Bad integer !\0a"'
  1157.                             return -1
  1158.                         end
  1159.                     xxx=result
  1160.                     xxx=xxx-pc+extwrd*2-4
  1161.  
  1162.                     if (xxx<=32767) & (xxx>=-32768) then call PushWord xxx
  1163.                     else
  1164.                         do
  1165.                             'print "Sorry, longword PC relative not supported !\0a"'
  1166.                             return -1
  1167.                         end
  1168.                     return 0
  1169.                 end
  1170.             else
  1171.                 do
  1172.                     if pos('PC',argum)=0 then
  1173.                         do
  1174.                             'print "Illegal base register !\0a"'
  1175.                             return -1
  1176.                         end
  1177.                     return ParseComplexArg(argum'|PC')
  1178.                 end
  1179.         end
  1180.     else
  1181.         do
  1182.             parse var argum ',A' reg
  1183.             return ParseComplexArg(argum'|A'substr(reg,1,1))
  1184.         end
  1185.     return 0
  1186.  
  1187.  
  1188. /*----------------------------------------------*/
  1189. /* Parse a complex addressing argument                */
  1190. /* and push words to memory                            */
  1191. /*                                                                */
  1192. /* Input   : addressing arg '|' base register    */
  1193. /* Uses    : c. extra pc extwrd                        */
  1194. /* Changes : c. extra                                    */
  1195. /* Returns : -1 if error or 0                            */
  1196. /*----------------------------------------------*/
  1197.  
  1198. ParseComplexArg: procedure expose c. extra pc extwrd
  1199. parse arg argum '|' basereg
  1200.  
  1201.     if substr(argum,2,1)='[' then
  1202.         do
  1203.             parse var argum '([' bd ',' (basereg) rest
  1204.  
  1205.             if substr(rest,1,1)=']' then
  1206.                 do
  1207.                     postidx=4
  1208.                     parse var rest '],' reg ',' od ')'
  1209.                 end
  1210.             else
  1211.                 do
  1212.                     postidx=0
  1213.                     parse var rest ',' reg '],' od ')'
  1214.                 end
  1215.             parse var reg reg '.' idxsize '*' multi
  1216.             'void' bd
  1217.             if rc~=0 then
  1218.                 do
  1219.                     'print "Bad integer !\0a"'
  1220.                     return -1
  1221.                 end
  1222.             bd=result
  1223.             if basereg='PC' then bd=bd-pc+extwrd*2-4
  1224.             'void' od
  1225.             if rc~=0 then
  1226.                 do
  1227.                     'print "Bad integer !\0a"'
  1228.                     return -1
  1229.                 end
  1230.             od=result
  1231.  
  1232.             if (idxsize='W') | (idxsize='') then idxsize=0
  1233.             else if idxsize='L' then idxsize=1
  1234.             else
  1235.                 do
  1236.                     'print "Bad index size specifier !\0a"'
  1237.                     return -1
  1238.                 end
  1239.  
  1240.             idxreg=regbits(reg)
  1241.             if idxreg=-1 then return -1
  1242.             if substr(reg,1,1)='A' then idxdata=1
  1243.             else idxdata=0
  1244.  
  1245.             if (multi='') | (multi='1') then multi=0
  1246.             else if multi='2' then multi=1
  1247.             else if multi='4' then multi=2
  1248.             else if multi='8' then multi=3
  1249.             else
  1250.                 do
  1251.                     'print "Bad index scale !\0a"'
  1252.                     return -1
  1253.                 end
  1254.  
  1255.             if (od>32767) | (od<-32768) then postidx=postidx+3
  1256.             else postidx=postidx+2
  1257.  
  1258.             if (bd>32767) | (bd<-32768) then baseidx=3
  1259.             else baseidx=2
  1260.  
  1261.             call PushWord idxdata*32768+idxreg*4096+idxsize*2048+multi*512+256+baseidx*16+postidx
  1262.  
  1263.             if (bd>32767) | (bd<-32768) then call PushLong bd
  1264.             else call PushWord bd
  1265.  
  1266.             if (od>32767) | (od<-32768) then call PushLong od
  1267.             else call PushWord od
  1268.  
  1269.             return 0
  1270.         end
  1271.     else
  1272.         do
  1273.             parse var argum '(' bd ',' (basereg) ',' reg ')'
  1274.  
  1275.             parse var reg reg '.' idxsize '*' multi
  1276.             'void' bd
  1277.             if rc~=0 then
  1278.                 do
  1279.                     'print "Bad integer !\0a"'
  1280.                     return -1
  1281.                 end
  1282.             bd=result
  1283.             if basereg='PC' then bd=bd-pc+extwrd*2-4
  1284.  
  1285.             if (idxsize='W') | (idxsize='') then idxsize=0
  1286.             else if idxsize='L' then idxsize=1
  1287.             else
  1288.                 do
  1289.                     'print "Bad index size specifier !\0a"'
  1290.                     return -1
  1291.                 end
  1292.  
  1293.             idxreg=regbits(reg)
  1294.             if idxreg=-1 then return -1
  1295.             if substr(reg,1,1)='A' then idxdata=1
  1296.             else idxdata=0
  1297.  
  1298.             if (multi='') | (multi='1') then multi=0
  1299.             else if multi='2' then multi=1
  1300.             else if multi='4' then multi=2
  1301.             else if multi='8' then multi=3
  1302.             else
  1303.                 do
  1304.                     'print "Bad index scale !\0a"'
  1305.                     return -1
  1306.                 end
  1307.  
  1308.             if (bd>127) | (bd<-128) then
  1309.                 do
  1310.                     last9=256+32
  1311.                     if (bd>32767) | (bd<-32768) then
  1312.                         do
  1313.                             last9=last9+16
  1314.                         end
  1315.                 end
  1316.             else last9=bd
  1317.  
  1318.             call PushWord idxdata*32768+idxreg*4096+idxsize*2048+multi*512+last9
  1319.  
  1320.             if (bd>127) | (bd<-128)then
  1321.                 do
  1322.                     if (bd>32767) | (bd<-32768) then call PushLong bd
  1323.                     else call PushWord bd
  1324.                 end
  1325.             return 0
  1326.         end
  1327.  
  1328.  
  1329. /*-------------------------------*/
  1330. /* Split argument in two parts    */
  1331. /* source and destination            */
  1332. /*                                            */
  1333. /* Input   : argument                */
  1334. /* Uses    :                            */
  1335. /* Changes : source dest            */
  1336. /* Returns :                            */
  1337. /*-------------------------------*/
  1338.  
  1339. SplitArgs: procedure expose source dest
  1340. parse arg arg
  1341.  
  1342.     parse var arg lsrc '(' source ')' rsrc ',' dest
  1343.     if source='' then
  1344.         do
  1345.             parse var arg source ',' dest
  1346.         end
  1347.     else if dest='' then
  1348.         do
  1349.             parse var arg source ',' dest
  1350.         end
  1351.     else source=lsrc'('source')'rsrc
  1352.     return
  1353.  
  1354.  
  1355. /*-------------------------------------*/
  1356. /* Convert register list to bit string    */
  1357. /*                                                    */
  1358. /* Input   : register list                    */
  1359. /* Uses    :                                    */
  1360. /* Changes :                                     */
  1361. /* Returns : bit string or -1 if error    */
  1362. /*-------------------------------------*/
  1363.  
  1364. RegListBits: procedure
  1365. parse arg list
  1366.  
  1367.     bits='0000000000000000'
  1368.     regs='D0D1D2D3D4D5D6D7A0A1A2A3A4A5A6A7'
  1369.     rest=list
  1370.     do until rest=''
  1371.         parse var rest one '/' rest
  1372.         parse var one left '-' right
  1373.         l=pos(left,regs)
  1374.         if l=0 then
  1375.             do
  1376.                 'print "Bad register !\0a"'
  1377.                 return -1
  1378.             end
  1379.         l=(l-1)/2+1
  1380.         if right='' then
  1381.             bits=overlay('1',bits,l,1)
  1382.         else
  1383.             do
  1384.                 r=pos(right,regs)
  1385.                 if r=0 then
  1386.                     do
  1387.                         'print "Bad register !\0a"'
  1388.                         return -1
  1389.                     end
  1390.                 r=(r-1)/2+1
  1391.                 if ((l<=8) & (r>8)) | ((l>8) & (r<=8)) then
  1392.                     do
  1393.                         'print "Bad register pair !\0a"'
  1394.                         return -1
  1395.                     end
  1396.                 do i=l to r
  1397.                     bits=overlay('1',bits,i,1)
  1398.                 end
  1399.             end
  1400.     end
  1401.     return bits
  1402.  
  1403.  
  1404. /*----------------------------*/
  1405. /* Convert integer to a byte    */
  1406. /*                                        */
  1407. /* Input   : integer                */
  1408. /* Uses    :                        */
  1409. /* Changes :                         */
  1410. /* Returns : byte                    */
  1411. /*----------------------------*/
  1412.  
  1413. MakeByte: procedure
  1414. parse arg int
  1415.  
  1416.     'void' int'&255'
  1417.     return result
  1418.  
  1419.  
  1420. /*----------------------------*/
  1421. /* Convert integer to a word    */
  1422. /*                                        */
  1423. /* Input   : integer                */
  1424. /* Uses    :                        */
  1425. /* Changes :                         */
  1426. /* Returns : word                    */
  1427. /*----------------------------*/
  1428.  
  1429. MakeWord: procedure
  1430. parse arg int
  1431.  
  1432.     'void' int'&65535'
  1433.     return result
  1434.  
  1435.  
  1436.